﻿using System;
using System.Collections.Generic;
using System.Web.Security;
using System.Web.UI.WebControls;
using Hematology.Data;
using Hematology.HmtMembership;
using Hematology.Tools;
using Hematology.Tools.Storage;
using Hematology.Tools.Text;
using Hematology.UserSite.Controls;
using NgoResource = Hematology.UserSite.App_GlobalResources.UserSite;

namespace Hematology.UserSite
{
	public partial class AccountProcessing : NgoPage
	{
		private static string _targetValidationGroup;

		#region Properties

		private EnumHelper.AccountProcessingSection CurrentAccountProcessingSection
		{
			get
			{
				return ViewState["CurrentAccountProcessingSection"] != null
						   ? (EnumHelper.AccountProcessingSection)Enum.Parse(typeof(EnumHelper.AccountProcessingSection), ViewState["CurrentAccountProcessingSection"].ToString())
						   : EnumHelper.AccountProcessingSection.Registration;

			}
			set { ViewState["CurrentAccountProcessingSection"] = value; }
		}

		private bool IsAdminRequest
		{
			get
			{
				return Convert.ToBoolean(ViewState["IsAdminRequest"]);
			}
			set
			{
				ViewState["IsAdminRequest"] = value;
			}
		}

		#endregion

		#region Page methods

		private void FillViewStateVariables()
		{
			CheckAdminRequest();

			string pageSection = Request.QueryString["view"];
			if (Array.IndexOf(Enum.GetNames(typeof(EnumHelper.AccountProcessingSection)), pageSection) > -1)
			{
				CurrentAccountProcessingSection =
					(EnumHelper.AccountProcessingSection)Enum.Parse(typeof(EnumHelper.AccountProcessingSection), pageSection);
			}
		}

		private void FillPage()
		{
			FillViewStateVariables();

			switch (CurrentAccountProcessingSection)
			{
				case EnumHelper.AccountProcessingSection.RemindPassword:
					mvAccountProcessing.ActiveViewIndex = 1;
					ptTitle.Text = NgoResource.resRemindPassword;
					_targetValidationGroup = "vgRemindPassword";
					break;
				case EnumHelper.AccountProcessingSection.ActivateNewPassword:
					ptTitle.Text = NgoResource.resRemindPassword;
					ActivateNewPassword();
					break;
				default:
					mvAccountProcessing.ActiveViewIndex = 0;
					ptTitle.Text = NgoResource.resRegistration;
					_targetValidationGroup = "vgRegistration";
					FillCountryCombo();
					FillCityCombo();
					FillJobCombo();
					break;
			}
		}

		#endregion

		#region Registration methods

		#region Fill methods

		private void FillJobCombo()
		{
			if (!String.IsNullOrEmpty(lbJobCountry.SelectedValue))
			{
				List<Job> lJob = Job.GetAllJobs(Convert.ToInt32(lbJobCountry.SelectedValue),
				                                null,
				                                !String.IsNullOrEmpty(lbJobCity.SelectedValue)
				                                	? Convert.ToInt32(lbJobCity.SelectedValue)
				                                	: (int?) null);
				lbJob.DataSource = lJob;
				lbJob.DataBind();
			}
		}

		private void FillCityCombo()
		{
			if (!String.IsNullOrEmpty(lbJobCountry.SelectedValue))
			{
				List<City> lCity = City.GetAllCities(Convert.ToInt32(lbJobCountry.SelectedValue), null, true);
				lbJobCity.DataSource = lCity;
				lbJobCity.DataBind();
			}
		}

		private void FillCountryCombo()
		{
			List<Country> lCountry = Country.GetAllCountries(true);
			lbJobCountry.DataSource = lCountry;
			lbJobCountry.DataBind();

			lbJobCountry.SelectedIndex = lCountry.FindIndex(country => country.Name == ConfigReader.DefaultCountry);
		}

		#endregion

		#region Other methods

		private SiteUserExtended SaveExtendedUserInfo(int iUserId)
		{
			SiteUserExtended accessUser = SiteUserExtended.Get(iUserId);

			accessUser.FirstName = txtFirstName.Text.Trim();
			accessUser.MiddleName = txtMiddleName.Text.Trim();
			accessUser.LastName = txtLastName.Text.Trim();
			accessUser.BirthDate = cpBirthDate.SelectedValue;

			if (!IsAdminRequest)
			{
				accessUser.JobId = Convert.ToInt32(lbJob.SelectedValue);
				accessUser.BaseInfo.Email = txtEmail.Text.Trim();
				accessUser.Phone1 = txtPhone1.Text.Trim();
				accessUser.Phone2 = txtPhone2.Text.Trim();
				accessUser.Skype = txtSkype.Text.Trim();
				accessUser.JobPosition = txtJobPosition.Text.Trim();
			}

			accessUser.Update();

			return accessUser;
		}

		private void CheckAdminRequest()
		{
			IsAdminRequest = false;
			string sIsRoleRequestString = Request.QueryString["role"];
			if (!String.IsNullOrEmpty(sIsRoleRequestString) && String.Compare(sIsRoleRequestString, "admin", true) == 0)
			{
				if (!MembershipHelper.RoleService.AdminExists())
				{
					upRegistration.Visible = false;
					IsAdminRequest = true;
				}
			}
		}

		private void ShowProcessingStatus(string sStatusText, string sTitleText, string sSubTitleText)
		{
			mvAccountProcessing.ActiveViewIndex = 2;
			lblResetPasswordStatus.Text = sStatusText;
			ptTitle.Text = sTitleText;
			lblProcessingStatus.Text = sSubTitleText;
		}

		#endregion

		#region Validation

		protected void vldPasswordsEquals_ServerValidate(object sender, ServerValidateEventArgs e)
		{
			e.IsValid = txtPassword.Text.Equals(txtRepeatPassword.Text);
		}

		protected void vldEmailNotExists_ServerValidate(object sender, ServerValidateEventArgs e)
		{
			bool bIsValid;
			CheckEmailRegistration(e.Value, true, out bIsValid);

			e.IsValid = !bIsValid;
		}

		#endregion

		#region Event handlers

		protected void btnSaveAccessUser_Click(object sender, EventArgs e)
		{
			if (Page.IsValid)
			{
				string sPassword = txtPassword.Text.Trim();
				string sEmail = txtEmail.Text.Trim();

				if (IsAdminRequest)
				{
					string sAdminRole = EnumHelper.RequiredRoles.Admin.ToString();

					MembershipHelper.RoleService.CreateRole(sAdminRole, "Администратор сайта");
					if (MembershipHelper.RoleService.RoleExists(sAdminRole) && !MembershipHelper.RoleService.AdminExists())
					{
						MembershipCreateStatus createStatus;
						MembershipUser newUser = MembershipHelper.MembershipService.CreateUser(sEmail, sPassword, true, out createStatus);
						if (createStatus == MembershipCreateStatus.Success)
						{
							SaveExtendedUserInfo(Convert.ToInt32(newUser.ProviderUserKey));
							MembershipHelper.RoleService.AddUsersToRoles(new[] { sEmail },
																		 new[] { sAdminRole });
							Response.Redirect("/");
						}
					}
				}
				else
				{
					string sUnconfirmedUser = EnumHelper.RequiredRoles.UnconfirmedUser.ToString();
					if (!MembershipHelper.RoleService.RoleExists(sUnconfirmedUser))
					{
						MembershipHelper.RoleService.CreateRole(sUnconfirmedUser, "Неподтверждённый пользователь");
					}

					MembershipCreateStatus createStatus;
					MembershipUser newUser = MembershipHelper.MembershipService.CreateUser(sEmail, sPassword, false, out createStatus);
					if (createStatus == MembershipCreateStatus.Success)
					{
						MembershipHelper.RoleService.AddUsersToRoles(new[] { sEmail },
																	 new[] { sUnconfirmedUser });

						SiteUserExtended accessUser = SaveExtendedUserInfo(Convert.ToInt32(newUser.ProviderUserKey));

						EmailTemplate etWelcome = EmailTemplate.GetEmailTemlateByType((int)EnumHelper.EmailTemplateType.Welcome);
						if (etWelcome == null)
							return;

						MailHelper.SendEmail(etWelcome,
											 accessUser.BaseInfo.Email,
											 false,
											 new[]
						                     	{
						                     		accessUser.FirstName,
						                     		accessUser.MiddleName,
						                     		accessUser.BaseInfo.Email,
						                     		sPassword
						                     	});
					}
				}
			}
		}

		protected void ddlJobCountry_SelectedIndexChanged(object sender, EventArgs e)
		{
			FillCityCombo();
			FillJobCombo();
		}

		protected void ddlJobCity_SelectedIndexChanged(object sender, EventArgs e)
		{
			FillJobCombo();
		}

		#endregion

		#endregion

		#region Remind password methods

		#region Event handlers

		protected void btnRemindPassword_Click(object sender, EventArgs e)
		{
			if (Page.IsValid)
			{
				SendNewPassword();
			}
		}

		#endregion

		#region Validation

		protected void vldRegisteredEmailExists_ServerValidate(object sender, ServerValidateEventArgs e)
		{
			bool bIsValid;
			SiteUserExtended remindedUser = CheckEmailRegistration(e.Value, true, out bIsValid);
			SessionHelper.RemindedUser = remindedUser;

			e.IsValid = bIsValid;
		}

		#endregion

		#region Other methods

		private void SendNewPassword()
		{
			if (SessionHelper.RemindedUser == null)
				return;

			EmailTemplate etRemindPassword = EmailTemplate.GetEmailTemlateByType((int)EnumHelper.EmailTemplateType.RemindPassword);
			if (etRemindPassword == null)
				return;

			MailHelper.SendEmail(etRemindPassword,
								 SessionHelper.RemindedUser.BaseInfo.Email,
								 false,
								 new[]
				                     	{
				                     		SessionHelper.RemindedUser.FirstName,
				                     		SessionHelper.RemindedUser.MiddleName,
				                     		DateTime.Now.ToLongDateString(),
				                     		SessionHelper.RemindedUser.BaseInfo.NewPasswordKey
				                     	});

			ShowProcessingStatus(
				NgoResource.resContinuePasswordRecoveryProcess,
				NgoResource.resRemindPassword,
				NgoResource.resStatus);
		}

		private void ActivateNewPassword()
		{
			if (Page.IsPostBack)
				return;

			string sNewPasswordKey = Request.QueryString["key"];
			if (!String.IsNullOrEmpty(sNewPasswordKey))
			{
				Guid sNewPasswordGuid = new Guid(sNewPasswordKey);
				if (sNewPasswordGuid == Guid.Empty)
				{
					ShowProcessingStatus(NgoResource.resInvalidPasswordKey, NgoResource.resRemindPassword, NgoResource.resError);
					return;
				}

				SiteUserExtended requestedNewPasswordUser = SiteUserExtended.SearchByPasswordKey(sNewPasswordKey);
				if (requestedNewPasswordUser == null || requestedNewPasswordUser.UserId == null)
				{
					ShowProcessingStatus(NgoResource.resInvalidPasswordKey, NgoResource.resRemindPassword, NgoResource.resError);
					return;
				}

				string sNewPassword = MembershipHelper.MembershipService.ResetPassword(requestedNewPasswordUser.BaseInfo.Email);
				if (String.IsNullOrEmpty(sNewPassword))
				{
					ShowProcessingStatus(NgoResource.resInvalidPasswordKey, NgoResource.resRemindPassword, NgoResource.resError);
					return;
				}

				SessionHelper.RemindedUser = SiteUserExtended.Get(requestedNewPasswordUser.UserId.Value);
				if (SessionHelper.RemindedUser == null)
				{
					ShowProcessingStatus(NgoResource.resInvalidPasswordKey, NgoResource.resRemindPassword, NgoResource.resError);
					return;
				}

				EmailTemplate etRequestNewPassword =
					EmailTemplate.GetEmailTemlateByType((int)EnumHelper.EmailTemplateType.RequestNewPassword);
				if (etRequestNewPassword == null)
				{
					ShowProcessingStatus(NgoResource.resInvalidPasswordKey, NgoResource.resRemindPassword, NgoResource.resError);
					return;
				}

				MailHelper.SendEmail(etRequestNewPassword,
									 requestedNewPasswordUser.BaseInfo.Email,
									 true,
									 new[]
					                     	{
					                     		requestedNewPasswordUser.FirstName,
					                     		requestedNewPasswordUser.MiddleName,
					                     		requestedNewPasswordUser.BaseInfo.Email,
					                     		sNewPassword
					                     	});

				SessionHelper.ResetPasswordStatus = true;
				Response.Redirect("/AccountProcessing.aspx?view=ActivateNewPassword");
			}
			else if (SessionHelper.ResetPasswordStatus.HasValue && SessionHelper.RemindedUser != null)
			{
				if (SessionHelper.ResetPasswordStatus.Value)
				{
					ShowProcessingStatus(NgoResource.resPasswordWasSuccessfullyChanged, NgoResource.resRemindPassword, NgoResource.resStatus);

					SessionHelper.RemindedUser.BaseInfo.NewPasswordKey = Guid.NewGuid().ToString();
					SessionHelper.RemindedUser.BaseInfo.UpdateInstance();

					SessionHelper.ResetPasswordStatus = null;
				}
			}
			else
			{
				Response.Redirect("/AccountProcessing.aspx?view=RemindPassword");
			}
		}

		#endregion

		#endregion

		private SiteUserExtended CheckEmailRegistration(string sEmail, bool bIsCheckForRegisteredEmail, out bool bIsValid)
		{
			SiteUserExtended remindedUser = SiteUserExtended.SearchByEmail(sEmail);

			bIsValid = bIsCheckForRegisteredEmail
						? remindedUser != null
						: remindedUser == null;

			return remindedUser;
		}

		protected void Page_Load(object sender, EventArgs e)
		{
			if (!Page.IsPostBack)
			{
				FillPage();
			}
		}

		protected void Page_PreRender(object sender, EventArgs e)
		{
			ValidationHelper.RegisterServerValidationMessageScript(Page, _targetValidationGroup);
		}
	}
}